from PySide2 import QtCore, QtGui
from PySide2.QtWidgets import QMessageBox, QMainWindow, QFileDialog

from main_ui import Ui_MainWindow

import sys

from PySide2.QtCore import QEventLoop, QTimer, QFileInfo

from srecordtool import SrecordTool


class EmittingStr(QtCore.QObject):
    # 重定向信号，用于定时向文本界面发送信息，这样可以实现一条一条显示的效果
    textWritten = QtCore.Signal(str)  # 定义一个发送str的信号，这里用的方法名与PyQt5不一样

    def write(self, text):
        self.textWritten.emit(str(text))
        loop = QEventLoop()
        QTimer.singleShot(20, loop.quit)
        loop.exec_()



class MyMainWindow(QMainWindow, Ui_MainWindow):
    def __init__(self, parent=None):
        super(MyMainWindow, self).__init__(parent)
        self.ui = Ui_MainWindow()
        self.ui.setupUi(self)

        self.paths = ""  # ==> 默认文本内容

        self.srectool = SrecordTool()

        sys.stdout = EmittingStr()
        self.ui.textEdit_log.connect(sys.stdout, QtCore.SIGNAL("textWritten(QString)"), self.output_written)
        sys.stderr = EmittingStr()
        self.ui.textEdit_log.connect(sys.stderr, QtCore.SIGNAL("textWritten(QString)"), self.output_written)

        self.ui.checkBox_addHead.clicked.connect(self.checkbox_addhead_clicked)
        self.ui.pushButton_readhex.clicked.connect(self.pushbutton_readhex_clicked)
        self.ui.pushButton_hexfile_select.clicked.connect(self.pushbutton_hexfile_select_clicked)
        self.ui.pushButton_binfile_select.clicked.connect(self.pushbutton_binfile_select_clicked)
        self.ui.pushButton_bin_save.clicked.connect(self.pushbutton_bin_save_clicked)

        # 允许拖拽文件
        self.setAcceptDrops(True)
        self.ui.lineEdit_hexfile.setAcceptDrops(False)
        self.ui.lineEdit_binfile.setAcceptDrops(False)
        self.ui.lineEdit_firmware_head.setAcceptDrops(False)
        self.ui.lineEdit_firmware_addr.setAcceptDrops(False)
        self.ui.lineEdit_firmware_length.setAcceptDrops(False)
        self.ui.textEdit_log.setAcceptDrops(False)

        print("操作提示：")
        print("1、选择或拖入hex文件，点击读取信息按钮")
        print("2、填写需要的文件头以及APP起始地址")
        print("3、选择生成文件保存位置(默认生成到软件当前目录)")
        print("4、点击生成按钮")

    def pushbutton_bin_save_clicked(self):
        # 获取hex文件文件路径
        ui_hexfile = self.ui.lineEdit_hexfile.text()
        if ui_hexfile == "":
            print("请先选择或拖入hex文件")
            return
        self.srectool.src_hex = ui_hexfile

        # 获取bin文件头部信息
        ui_head = self.ui.lineEdit_firmware_head.text()
        if ui_head == "":
            print("请先填写文件头")
            return
        self.srectool.head = int(ui_head, 16)

        # 获取APP起始地址
        ui_baseaddr = self.ui.lineEdit_firmware_addr.text()
        if ui_baseaddr == "":
            print("请先填写APP起始地址")
            return
        self.srectool.base_addr = int(ui_baseaddr, 16)

        ui_binfile = self.ui.lineEdit_binfile.text()
        if ui_binfile == "":
            print("请选择保存位置及文件名")
            return
        self.srectool.dist_bin = ui_binfile

        print("当前文件头：", hex(self.srectool.head))
        print("当前APP起始地址：", hex(self.srectool.base_addr))

        self.srectool.get_bin_length()
        print("原始固件长度：", self.srectool.size)
        print("原始固件长度HEX：", hex(self.srectool.size))
        self.ui.lineEdit_firmware_length.setText(str(self.srectool.size))

        self.srectool.hex_add_crc(self.ui.checkBox_addHead.isChecked())

        self.srectool.hex2bin(self.ui.checkBox_addHead.isChecked())
        print("固件生成成功！\r\n"
              "生成文件:  " + self.ui.lineEdit_binfile.text() +
              "\r\n----------------\r\n\r\n")
        QMessageBox.information(self, "提示", "固件生成:\r\n" + self.ui.lineEdit_binfile.text())

    def pushbutton_binfile_select_clicked(self):
        file_dialog = QFileDialog()
        file_path, _ = file_dialog.getSaveFileName(self, "Select BIN File", "", "BIN Files (*.bin)")
        if file_path:
            self.ui.lineEdit_binfile.setText(file_path)
            print("即将生成文件：", file_path)

    def pushbutton_hexfile_select_clicked(self):
        hexfile_path, _ = QFileDialog.getOpenFileName(self, '选择hex文件', './', 'Hex Files (*.hex)')
        if hexfile_path:
            self.ui.lineEdit_hexfile.setText(hexfile_path)
            print("已选择文件：", hexfile_path)

    def pushbutton_readhex_clicked(self):
        if self.srectool.get_hex_start_addr(self.ui.lineEdit_hexfile.text()):
            self.ui.lineEdit_firmware_addr.setText(hex(self.srectool.base_addr))
            print("已读取hex文件信息\r\n已获取APP起始地址:", hex(self.srectool.base_addr))

    def dragEnterEvent(self, event):
        # 鼠标拖入事件
        filename = event.mimeData().urls()[0].fileName()  # ==> 获取文件路径
        # print("拖入文件名" + filename)
        fileInfo = QFileInfo(filename)
        ext = fileInfo.suffix().upper()  # 获取文件后缀名
        if ext == "HEX":
            print("放入HEX文件为：" + filename)
            event.acceptProposedAction()  # 接受拖拽事件
        else:
            print("文件格式错误，请放入HEX文件")
            event.ignore()  # 忽略拖拽事件

    def dropEvent(self, event):
        filename = event.mimeData().urls()[0].path()
        # 去掉第一个斜杠
        filename = filename[1:]
        self.ui.lineEdit_hexfile.setText(filename)
        event.accept()
        # print(filename)

    def checkbox_addhead_clicked(self, checked):
        self.ui.lineEdit_firmware_head.setEnabled(checked)

    # 这个装饰器不加也行，下面edt_log要改成你自己文本框的名字
    def output_written(self, text):
        # self.edt_log.clear()
        cursor = self.ui.textEdit_log.textCursor()
        cursor.movePosition(QtGui.QTextCursor.End)
        cursor.insertText(text)
        self.ui.textEdit_log.setTextCursor(cursor)
        self.ui.textEdit_log.ensureCursorVisible()
